package com.example.demo.config;

import org.springframework.cache.Cache;
import org.springframework.cache.support.SimpleValueWrapper;

import java.util.concurrent.*;

/*实现ttl功能*/
public class TtlCache implements Cache {

    private final Cache delegate;
    private final ConcurrentMap<Object, Long> expirationTimes = new ConcurrentHashMap<>();
    private final long defaultTtl;
    private final TimeUnit timeUnit;

    public TtlCache(Cache delegate, long defaultTtl, TimeUnit timeUnit) {
        this.delegate = delegate;
        this.defaultTtl = defaultTtl;
        this.timeUnit = timeUnit;
    }

    @Override
    public String getName() {
        return delegate.getName();
    }

    @Override
    public Object getNativeCache() {
        return delegate.getNativeCache();
    }

    @Override
    public ValueWrapper get(Object key) {
        if (isExpired(key)) {
            evict(key);
            return null;
        }
        return delegate.get(key);
    }

    @Override
    public <T> T get(Object key, Class<T> type) {
        if (isExpired(key)) {
            evict(key);
            return null;
        }
        return delegate.get(key, type);
    }

    @Override
    public <T> T get(Object key, Callable<T> valueLoader) {
        // 检查缓存是否存在且未过期
        ValueWrapper wrapper = get(key);
        if (wrapper != null) {
            return (T) wrapper.get();
        }

        // 缓存未命中，使用valueLoader加载值
        try {
            T value = valueLoader.call();
            if (value != null) {
                put(key, value); // 使用默认TTL
                return value;
            }
        } catch (Exception e) {
            throw new ValueRetrievalException(key, valueLoader, e);
        }
        return null;
    }

    @Override
    public void put(Object key, Object value) {
        put(key, value, defaultTtl, timeUnit);
    }

    public void put(Object key, Object value, long ttl, TimeUnit timeUnit) {
        long expirationTime = System.currentTimeMillis() + timeUnit.toMillis(ttl);
        expirationTimes.put(key, expirationTime);
        delegate.put(key, value);
    }

    @Override
    public ValueWrapper putIfAbsent(Object key, Object value) {
        // 简化实现，实际应考虑原子性
        if (get(key) == null) {
            put(key, value);
            return new SimpleValueWrapper(value);
        }
        return get(key);
    }

    @Override
    public void evict(Object key) {
        expirationTimes.remove(key);
        delegate.evict(key);
    }

    @Override
    public void clear() {
        expirationTimes.clear();
        delegate.clear();
    }

    private boolean isExpired(Object key) {
        Long expirationTime = expirationTimes.get(key);
        return expirationTime != null && System.currentTimeMillis() > expirationTime;
    }
}